/*
 * Picture.java	1.0  01/02/2006
 * Picture.java	2.0  10/02/2008
 *
 * This class contains the OpenGL component that  
 * receives, calls, and processes OpenGL functions 
 * on the original picture
 * Author:    Isabelle Bichindaritz
 *
 */

import java.io.*;
import java.nio.*;
import java.awt.image.*;
import java.awt.*;
import java.awt.event.*;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;

public class Picture implements GLEventListener {
    
private GLAutoDrawable glDrawable;			// the drawable where OpenGL operates
private byte[] rgba;				// raster
private GLJPanel panel;				// copy of the panel that displays this picture
private String eventType = "";			// event type from mouse listener
private MouseEvent event;			// event sent by mouse listener
int height, width; 				// eight and width of the original image
int first = 0;					// first time in this instance
private byte[] color;				// color of a pixel to copy
private Point focus;				// point of focus	

public Picture(GLJPanel p) {
// set the panel to 'p'
	panel = p;
}

public void init(GLAutoDrawable drawable)
// intialization of the drawable
   {
// System.out.println("Picture init");
       final GL gl = drawable.getGL();
       final GLU glu = new GLU();      
   }

public void display(GLAutoDrawable drawable)
// display called whenever something needs to be drawn on the drawable
// if necessary, this method is invoked from display() whenever we 
// want to refresh the display
   {
// System.out.println("Picture display");
// initializations
       if (glDrawable == null) { glDrawable = drawable;};
       final GL gl = drawable.getGL();
       final GLU glu = new GLU();
       gl.glClearColor(1.0f, 1.7f, 1.7f, 1.0f);
       int frameHeight = height;
       frameHeight = Painter.frameHeight;
// the first time, clear the screen and load the original picture raster sent by Painter
       if (first == 0) {gl.glClear(GL.GL_COLOR_BUFFER_BIT); first = 1; displayImageRGBA(drawable);};

// display a red pixel following the movements of the brush on the Painting panel
	if (focus != null)
  	{
//System.out.println("saved focus x=" + event.getX() + ", y=" + event.getY());
        }
	else 
  	{// System.out.println("focus null"); 
       };

	if ((eventType.equals("mouse entered")) && (event.getY() < height)
						&& (event.getY() >= 0))
		{ focus = new Point (event.getX(), height - 1 - event.getY());
      		  gl.glBlendFunc (GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
      		  gl.glDisable(GL.GL_DEPTH_TEST);
      		  gl.glEnable (GL.GL_BLEND);
      		  gl.glRasterPos2i (0, 0);
       		  gl.glPointSize( 3.0f);
		  if (rgba == null) {
			// System.out.println ("Picture picture is NULL");
			}
		  else
			{
//System.out.println("drawn focus x=" + event.getX() + ", y=" + event.getY());
			 gl.glColor3f( 1.0f, 0.0f, 0.0f );    // point of focus shows in RED !!
			 gl.glBegin (GL.GL_POINTS);
				gl.glVertex2d (focus.getX(), focus.getY());
				gl.glVertex2d (focus.getX()+ 1, focus.getY());
				gl.glVertex2d (focus.getX(), focus.getY() + 1);
				gl.glVertex2d (focus.getX() + 1, focus.getY() + 1);
			 gl.glEnd(); 
		  	 eventType = "";
			}
	   	}
	else if (((eventType.equals("mouse moved")) ||(eventType.equals("mouse dragged")) 
                  || (eventType.equals("mouse pressed")) ||(eventType.equals("mouse released"))) 
			&& (event.getY() < height)
			&& (event.getY() >= 0) ) 
		{if (rgba == null) {
			// System.out.println ("Picture picture is NULL");
			}
		     else
			{
//System.out.println("cleaned focus x=" + event.getX() + ", y=" + event.getY());			
			 byte[] color = new byte[3];
			 this.init(drawable);
			 color = Painter.getOriginalPixel (new Point(focus.x, focus.y - 37));
			 gl.glColor3ubv( ByteBuffer.wrap(color) );   // restore original color in place of red dot
			 gl.glBegin (GL.GL_POINTS);
				gl.glVertex2d (focus.getX(), focus.getY() - 37);
			 gl.glEnd(); 
			 focus = new Point (event.getX(), height - 1 - event.getY());
			 gl.glColor3f( 1.0f, 0.0f, 0.0f );
			 gl.glBegin (GL.GL_POINTS);
				gl.glVertex2d (focus.getX(), focus.getY() - 37);
			 gl.glEnd(); 
//System.out.println("drawn focus x=" + event.getX() + ", y=" + event.getY());
		  	 eventType = "";
			};
		}
	else if ((eventType.equals("mouse exited"))) 
    		{if (rgba == null) {
			// System.out.println ("Picture picture is NULL");
			}
		  else
			{
//System.out.println("last erased focus x=" + event.getX() + ", y=" + event.getY());
			 byte[] color = new byte[3];
			 color = Painter.getOriginalPixel (focus);
			 gl.glColor3ubv( ByteBuffer.wrap(color) );   // restore original color in place of red dot
			 gl.glBegin (GL.GL_POINTS);
				gl.glVertex2d (focus.getX(), focus.getY());
			 gl.glEnd(); 
			};
		  eventType = "";
		  focus = null; 
		};
		
}

public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h)
// redraws the drawable with this new size
   {
    // System.out.println("Picture reshape width=" + width + "  height=" + height);
    // System.out.println("drawable=" + drawable);
       final GL gl = drawable.getGL();
       final GLU glu = new GLU();
	gl.glViewport (0, 0, width, height);
	gl.glMatrixMode( GL.GL_PROJECTION);
        gl.glLoadIdentity();
	glu.gluOrtho2D(0.0, width, 0.0, height);   // erases other objects
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
}

public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged)
// called whenever the display is changed
   {
    // System.out.println("Picture displayChanged");
   }

public void setImage(byte[] img, int w, int h) {
// initializes the image, its width, and its height
   // System.out.println("Picture setImage");

	rgba = img;
	width = w;
	height = h;
}


private void displayTriangle (GLAutoDrawable drawable) {
// for test purposes
      final GL gl = drawable.getGL();
      final GLU glu = new GLU();
      gl.glColor3f(1.0f, 0.0f, 0.0f );

       gl.glBegin( GL.GL_TRIANGLES );
           gl.glVertex2i( 400, 50 );
           gl.glVertex2i( 400, 100);
           gl.glVertex2i( 420, 75 );
       gl.glEnd();	
}

 
protected void displayImageRGBA (GLAutoDrawable drawable) {
// displays the original picture from its raster on the drawable
// System.out.println( "Picture displayRGBA");
     if (rgba != null)
     {
     	final GL gl = drawable.getGL();
      	final GLU glu = new GLU();
        // enable alpha mask (import from gif sets alpha bits)
        gl.glBlendFunc (GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
        gl.glEnable (GL.GL_BLEND);
        

        
        // draw bytes into OpenGL
        gl.glRasterPos2i (0, 0);
        // System.out.println ("Image, width=" +
        //                    width + ", height=" + height);
        gl.glDrawPixels (width, height, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, ByteBuffer.wrap(rgba));
	gl.glFlush();
	}
    }

public void setEventType (String type, MouseEvent e) {
// passes the event type and event from mouse on Painting panel	
	eventType = type;
	event = e;
}


} // end Picture class
